package de.swta.freezay.admin.item;

import de.swta.freezay.components.UnitChoiceRenderer;
import de.swta.freezay.components.CategoryChoiceRenderer;
import de.swta.freezay.admin.category.CategoryEditPanel;
import de.swta.freezay.database.JPAController;
import de.swta.freezay.database.controller.exceptions.NonexistentEntityException;
import de.swta.freezay.database.controller.exceptions.PreexistingEntityException;
import de.swta.freezay.database.dbEntities.Category;
import de.swta.freezay.database.dbEntities.Item;
import de.swta.freezay.database.dbEntities.Unit;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.RequiredTextField;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.validation.validator.RangeValidator;
import org.apache.wicket.validation.validator.StringValidator.LengthBetweenValidator;

public abstract class ItemEditPanel extends Panel {

    /** Input form to edit an item. */
    Form itemForm;
    /** EditMode - true if an item is edited. False otherwise. */
    boolean editMode;

    /**
     * Creates a new instance of ItemEditPanel.
     *
     * @param id panel id.
     * @param itemId Id of the item to edit.
     * @param editMode True if an item is edited. False otherwise
     */
    public ItemEditPanel(String id, int itemId, boolean editMode) {
        super(id);

        this.editMode = editMode;
        init(itemId);
    }

    /**
     * Initializes the panel with all components.
     *
     * @param itemId Id of the item to edit.
     */
    private void init(int itemId) {
        Item i;

        if (editMode) {
            /** if item is edited - find it. */
            i = JPAController.ItemJpaController.findItem(itemId);
        } else {
            /** if item is new - create it. */
            i = new Item();
        }
        itemForm = new Form("itemForm");
        
        itemForm.add(new AjaxSubmitLink("saveLink") {

            @Override
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                /* If submit was clicked - it is saved in DB. */
                Item i = (Item) itemForm.getModelObject();

                if (editMode) {
                    /* If it was edited - it is edited in DB. */
                    try {
                        JPAController.ItemJpaController.edit(i);
                    } catch (NonexistentEntityException ex) {
                        Logger.getLogger(CategoryEditPanel.class.getName()).log(
                                        Level.SEVERE, null, ex);
                    } catch (Exception ex) {
                        Logger.getLogger(CategoryEditPanel.class.getName()).log(
                                        Level.SEVERE, null, ex);
                    }
                } else {
                    /* Otherwise it is created. */
                    try {
                        JPAController.ItemJpaController.create(i);
                    } catch (PreexistingEntityException ex) {
                        Logger.getLogger(CategoryEditPanel.class.getName()).log(
                                        Level.SEVERE, null, ex);
                    } catch (Exception ex) {
                        Logger.getLogger(CategoryEditPanel.class.getName()).log(
                                        Level.SEVERE, null, ex);
                    }
                }
                ItemEditPanel.this.confirmLinkClicked(target);
            }

            /**
             * Handles error- messages and write it in the feedbackpanel.
             */
            @Override
            protected void onError(AjaxRequestTarget target, Form<?> form) {
                target.addComponent(this.getParent().get("feedback"));
                super.onError(target, form);
            }
        });

        /* Components of the form. */
        itemForm.add(new RequiredTextField("name").add(new LengthBetweenValidator(3, 40)));
        itemForm.add(new TextArea("description"));
        final PropertyModel<Category> categoryChoicePropertyModel
                = new PropertyModel<Category>(i, "category");
        /* create the dropdown component with choices of categories*/
        DropDownChoice<Category> categoryChoice = new DropDownChoice<Category>(
                "category",
                categoryChoicePropertyModel,
                JPAController.CategoryJpaController.findCategoryEntities(),
                new CategoryChoiceRenderer());

        itemForm.add(categoryChoice);
        itemForm.add(new RequiredTextField("amount").add(new RangeValidator(1d, 5000d)));
        final PropertyModel<Unit> unitChoicePropertyModel
                = new PropertyModel<Unit>(i, "unit");
        
        /* create the dropdown component with choices of units*/
        DropDownChoice<Unit> unitChoice = new DropDownChoice<Unit>(
                "unit",
                unitChoicePropertyModel,
                JPAController.UnitJpaController.findUnitEntities(),
                new UnitChoiceRenderer());

        itemForm.add(unitChoice);
        RequiredTextField priceField = (RequiredTextField) new RequiredTextField("price").add(
                        new RangeValidator(1d, 2000d));

        /* if the item is reserved - the price should not edited. */
        if (i.isReserved()) {
           priceField.setEnabled(false);
        }
        itemForm.add(priceField);
        itemForm.setModel(new CompoundPropertyModel(i));
        itemForm.add(new FeedbackPanel("feedback").setOutputMarkupId(true));
        add(itemForm);
    }


    /**
     * Handles the actions after the confirm link was clicked.
     *
     * @param target AjaxRequestTarget.
     */
    public abstract void confirmLinkClicked(AjaxRequestTarget target);
}

